import 'dart:async';
import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter_massage/common_lib/index.dart';
import 'package:flutter_massage/pages/message/message_bean.dart';
import 'package:flutter_massage/pages/model/bean.dart';
import 'package:flutter_massage/pages/my/address/address_bean.dart';
import 'package:flutter_massage/pages/technician/place_order/order_bean.dart';
import 'package:flutter_massage/sqlite/db_constant.dart';
import 'package:flutter_massage/sqlite/db_interface.dart';
import 'package:flutter_massage/values/constant.dart';
import 'package:sqflite/sqflite.dart';

class DbImplements implements DbInterface {
  Database? _database;

  String get getUserKey => Storage().getString(StorageKey.userKey);

  @override
  Future openDb() async {
    String databasesPath = await getDatabasesPath();
    await _safeOperate(() async {
      _database = await openDatabase(
        '$databasesPath/${DbConstant.dbName}',
        version: DbConstant.dbVersion,
        onOpen: (Database db) async {
          _database = db;
          await Future.wait([
            createAddressTable(),
            createChatTable(),
            createMessageTable(),
            createOrderTable(),
          ]);
        },
        onCreate: (Database db, int version) async {
          _database = db;
          await Future.wait([
            createAddressTable(),
            createChatTable(),
            createMessageTable(),
            createOrderTable(),
          ]);
        },
      );
    }, '打开数据库失败');
  }

  @override
  Future closeDb() async {
    await _safeOperate(() async {
      await _database?.close();
    }, '关闭数据库失败');
  }

  ///创建地址表
  Future createAddressTable() async {
    await _safeOperate(() async {
      await _database?.execute('''
CREATE TABLE IF NOT EXISTS ${DbConstant.address} (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT,
  "$jsonKeyAddressBeanUserId" TEXT,
  "$jsonKeyAddressBeanName" TEXT,
  "$jsonKeyAddressBeanGender" TEXT,
  "$jsonKeyAddressBeanPhone" TEXT,
  "$jsonKeyAddressBeanAddress" TEXT,
  "$jsonKeyAddressBeanAddressId" TEXT,
  "$jsonKeyAddressBeanUpdateTime" TEXT
);
    ''');
    }, '创建地址表失败');
  }

  ///创建会话表
  Future createChatTable() async {
    await _safeOperate(() async {
      await _database?.execute('''
CREATE TABLE IF NOT EXISTS ${DbConstant.chat} (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT,
  "$jsonKeyChatBeanChatId" TEXT,
  "$jsonKeyChatBeanName" TEXT,
  "$jsonKeyChatBeanAvatar" TEXT,
  "$jsonKeyChatBeanMessage" TEXT,
  "$jsonKeyChatBeanUpdateTime" TEXT,
  "$jsonKeyChatBeanUserId" TEXT
);
    ''');
    }, '创建会话表失败');
  }

  ///创建消息表
  Future createMessageTable() async {
    await _safeOperate(() async {
      await _database?.execute('''
CREATE TABLE IF NOT EXISTS ${DbConstant.message} (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT,
  "$jsonKeyMessageBeanChatId" TEXT,
  "$jsonKeyMessageBeanMessageId" TEXT,
  "$jsonKeyMessageBeanFromId" TEXT,
  "$jsonKeyMessageBeanFromName" TEXT,
  "$jsonKeyMessageBeanToId" TEXT,
  "$jsonKeyMessageBeanToName" TEXT,
  "$jsonKeyMessageBeanAvatar" TEXT,
  "$jsonKeyMessageBeanMessage" TEXT,
  "$jsonKeyMessageBeanUpdateTime" TEXT
);
    ''');
    }, '创建消息表失败');
  }

  ///创建订单表
  Future createOrderTable() async {
    await _safeOperate(() async {
      await _database?.execute('''
CREATE TABLE IF NOT EXISTS ${DbConstant.order} (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  order_id TEXT,
  user_id TEXT,
  time TEXT,
  desc TEXT,
  address TEXT,
  technician TEXT,
  project TEXT,
  timestamp INTEGER
);
    ''');
    }, '创建订单表失败');
  }

  @override
  Future addAddress(AddressBean addressBean) async {
    addressBean.userId = getUserKey;
    addressBean.updateTime = DateTime.now().millisecondsSinceEpoch.toString();
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        await txn.insert(
          DbConstant.address,
          addressBean.toJson(),
          conflictAlgorithm: ConflictAlgorithm.replace,
        );
      });
    }, '地址保存失败');
  }

  @override
  Future deleteAddress(String addressId) async {
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        await txn.delete(
          DbConstant.address,
          where: '$jsonKeyAddressBeanAddressId = ?',
          whereArgs: [addressId],
        );
      });
    }, '地址删除失败');
  }

  @override
  Future editAddress(AddressBean addressBean) async {
    addressBean.userId = getUserKey;
    addressBean.updateTime = DateTime.now().millisecondsSinceEpoch.toString();
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        await txn.update(
          DbConstant.address,
          addressBean.toJson(),
          where: '$jsonKeyAddressBeanAddressId = ?',
          whereArgs: [addressBean.addressId],
        );
      });
    }, '地址更新失败');
  }

  @override
  Future<List<AddressBean>> getAddressList() async {
    Completer<List<AddressBean>> completer = Completer();
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        List<Map> result = await txn.query(
          DbConstant.address,
          where: '$jsonKeyAddressBeanUserId = ?',
          whereArgs: [getUserKey],
          orderBy: '$jsonKeyAddressBeanUpdateTime DESC',
        );
        List<AddressBean> addressList = result.map((e) => AddressBean.fromJson(e)).toList();
        completer.complete(addressList);
      });
    }, '地址列表读取失败');
    return completer.future;
  }

  Future _safeOperate(Future Function() operate, String errorMsg) async {
    try {
      await operate();
    } catch (e) {
      if (kDebugMode) {
        print(errorMsg);
      }
    }
  }

  @override
  Future<List<ChatBean>> getChatList({required String userId}) async {
    Completer<List<ChatBean>> completer = Completer();
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        List<Map> result = await txn.query(
          DbConstant.chat,
          where: '$jsonKeyChatBeanUserId = ?',
          whereArgs: [userId],
          orderBy: '$jsonKeyChatBeanUpdateTime DESC',
        );
        List<ChatBean> chatList = result.map((e) => ChatBean.fromJson(e)).toList();
        completer.complete(chatList);
      });
    }, '会话列表读取失败');
    return completer.future;
  }

  @override
  Future<List<MessageBean>> getMessageList({required String chatId}) async {
    Completer<List<MessageBean>> completer = Completer();
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        List<Map> result = await txn.query(
          DbConstant.message,
          where: '$jsonKeyMessageBeanChatId = ?',
          whereArgs: [chatId],
          orderBy: '$jsonKeyMessageBeanUpdateTime DESC',
        );
        List<MessageBean> messageList = result.map((e) => MessageBean.fromJson(e)).toList();
        completer.complete(messageList);
      });
    }, '消息列表读取失败');
    return completer.future;
  }

  @override
  Future insertMessage({required MessageBean messageBean}) async {
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        await txn.insert(
          DbConstant.message,
          messageBean.toJson(),
          conflictAlgorithm: ConflictAlgorithm.replace,
        );
      });
    }, '消息保存失败');
  }

  @override
  Future updateChat({required ChatBean bean}) async {
    ///1.查询库里是否有记录
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        List<Map> result = await txn.query(
          DbConstant.chat,
          where: '$jsonKeyChatBeanChatId = ?',
          whereArgs: [bean.chatId],
          limit: 1,
        );
        if (result.isEmpty) {
          ///插入
          await txn.insert(
            DbConstant.chat,
            bean.toJson(),
            conflictAlgorithm: ConflictAlgorithm.replace,
          );
        } else {
          ///更新
          await txn.update(
            DbConstant.chat,
            bean.toJson(),
            where: '$jsonKeyChatBeanChatId = ?',
            whereArgs: [bean.chatId],
            conflictAlgorithm: ConflictAlgorithm.replace,
          );
        }
      });
    }, '会话更新失败');
  }

  @override
  Future updateChatLastMessage({required String chatId, required String lastMessage}) async {
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        List<Map<String, Object?>> result = await txn.query(
          DbConstant.chat,
          where: '$jsonKeyChatBeanChatId = ?',
          whereArgs: [chatId],
          limit: 1,
        );
        if (result.isNotEmpty) {
          ChatBean bean = ChatBean.fromJson(result.first);
          bean.message = lastMessage;

          ///插入
          await txn.update(
            DbConstant.chat,
            bean.toJson(),
            where: '$jsonKeyChatBeanChatId = ?',
            whereArgs: [chatId],
            conflictAlgorithm: ConflictAlgorithm.replace,
          );
        }
      });
    }, '会话lastMessage更新失败');
  }

  @override
  Future saveOrder({
    required String orderId,
    required String time,
    required String desc,
    required AddressBean addressBean,
    required TechnicianBean technicianBean,
    required ProjectBean projectBean,
  }) async {
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        List<Map<String, Object?>> result = await txn.query(
          DbConstant.order,
          where: 'order_id = ? AND user_id = ?', //查询条件
          whereArgs: [orderId, getUserKey],
          limit: 1,
        );

        if (Loading.predicate(() => result.isNotEmpty, '订单已存在')) return;

        ///插入
        await txn.insert(
          DbConstant.order,
          {
            'order_id': orderId,
            'user_id': getUserKey,
            'time': time,
            'desc': desc,
            'address': jsonEncode(addressBean.toJson()),
            'technician': jsonEncode(technicianBean.toJson()),
            'project': jsonEncode(projectBean.toJson()),
            'timestamp': DateTime.now().millisecondsSinceEpoch,
          },
        );
      });
    }, 'saveOrder失败');
  }

  @override
  void getOrderList({required ValueChanged<List<OrderBean>> complete}) async {
    await _safeOperate(() async {
      await _database?.transaction((txn) async {
        List<Map<String, Object?>> result = await txn.query(
          DbConstant.order,
          where: 'user_id = ?',
          whereArgs: [getUserKey],
          limit: 100,
          orderBy: 'timestamp DESC',
        );
        List<OrderBean> orderList = [];
        for (var element in result) {
          orderList.add(OrderBean(
            orderId: element['order_id'] as String,
            userId: element['user_id'] as String,
            time: element['time'] as String,
            desc: element['desc'] as String,
            addressBean: AddressBean.fromJson(jsonDecode(element['address'] as String)),
            technicianBean: TechnicianBean.fromJson(jsonDecode(element['technician'] as String)),
            projectBean: ProjectBean.fromJson(jsonDecode(element['project'] as String)),
            timestamp: 0,
          ));
        }
        complete.call(orderList);
      });
    }, '订单列表查询失败');
  }
}
